package fr.cephb.joperon.core.db;


import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.sleepycat.db.DatabaseException;


import fr.cephb.joperon.core.Operon;
import fr.cephb.joperon.core.bio.Assembly;
import fr.cephb.joperon.core.bio.Chromosome;
import fr.cephb.joperon.core.db.base.BaseGBuildDB;
import fr.cephb.joperon.core.entities.GBuild;
import fr.cephb.util.CloseableIterator;

/**
 * Impelementation of BaseGBuildDB.
 * This class contains a method to get an information about all the chromosomes
 * in this build
 * @author operon
 */
public class GBuildDB
extends BaseGBuildDB
//OperonDBSingleValue.STRING<GBuild>
//implements AssemblyDB
	{
	/** information about a chromosome */
	public static class ChromInfo
		{
		private Chromosome chrom;
		private long start=Long.MAX_VALUE;
		private long end=Long.MIN_VALUE;
		public Chromosome getChromosome()
			{
			return chrom;
			}
		public long getStart()
			{
			return start;
			}
		public long getEnd()
			{
			return end;
			}
		public long getLength()
			{
			return end-start+1L;
			}
		@Override
		public String toString() {
			return getChromosome().toString()+"("+getLength()+"pb)";
			}
		}
	
	
	public GBuildDB(Operon operon,Assembly assembly)
		{
		super(operon,assembly);
		}
	

	public GBuildDB(Operon operon)
		{
		super(operon);
		}
	
	
	
	/** return information about the given chromosome on this build or null if the chromosome is not present */
	public ChromInfo getChromosome(Chromosome chrom)
		throws DatabaseException
		{
		for(ChromInfo ci: getChromosomes())
			{
			if(ci.getChromosome().equals(chrom)) return ci;
			}
		return null;
		}
	
	/** returns all the distincts chromosomes information on this build */
	public List<ChromInfo> getChromosomes()
		throws DatabaseException
		{
		ValueIterator iter=null;
		try
			{
			iter=this.listValues();
			Map<Chromosome,ChromInfo> map= new TreeMap<Chromosome, ChromInfo>();
			while(iter.hasNext())
				{
				GBuild build = iter.next();
				if(build.getChromosome()==null || build.getQ()<=build.getP()) continue;
				ChromInfo ci= map.get(build.getChromosome());
				if(ci==null)
					{
					ci= new ChromInfo();
					ci.chrom= build.getChromosome();
					map.put(ci.chrom,ci);
					}	
				ci.start = Math.min(ci.start,build.getP());
				ci.end = Math.max(ci.end,build.getQ());
				}
			
			return new ArrayList<ChromInfo>(map.values());

			}
		catch(DatabaseException err)
			{
			throw err;
			}
		catch(Throwable err)
			{
			throw new DatabaseException(err);
			}
		finally
			{
			if(iter!=null) iter.close();
			}
		
		}
	
	public static void main(String[] args)
		{
		try {
			Operon operon= Operon.newInstance();
			GBuildDB db= new GBuildDB(operon,Assembly.HSA_NCBI_BUILD_36);
			db.open();
			int i=0;
			CloseableIterator<GBuild> iter=db.listValues();
			long maxLeng=0;
			while(iter.hasNext())
				{
				if(i++>500) break;
				GBuild g=iter.next();
				if(!g.getChr().equals("1")) continue;
				maxLeng= Math.max(g.getQ(),maxLeng);
				System.err.println(g);
				}
			iter.close();
			
			
			System.err.println(db.containsKey("NT_113974.1"));
			System.err.println(db.containsKey("azdazdazdazd"));
			System.err.println(maxLeng);
			db.close();
			operon.close();
			System.err.println(i);
		} catch (Exception e) {
			e.printStackTrace();
		}
		}
	
	
	}
